﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;
using System.Xml.Serialization;
using DataAccessor.Protector;

namespace DataAccessor.Tools
{
    public partial class FormPrimary : Form
    {
        #region fields&properties
        /// <summary>
        /// all tsql xml document
        /// </summary>
        private Dictionary<int, TSQL> _tsqlCache = new Dictionary<int, TSQL>();
        /// <summary>
        /// Holistic file
        /// </summary>
        private FileInfo _holisticFileInfo;
        /// <summary>
        /// Holistic object
        /// </summary>
        private Holistic _holistic;
        private readonly string HOLISTIC_NAMESPACE = "http://dataaccessor.codeplex.com/xsd/holistic";
        private readonly string TSQL_NAMESPACE = "http://dataaccessor.codeplex.com/xsd/tsql";
        #endregion

        /// <summary>
        /// constractor
        /// </summary>
        public FormPrimary()
        {
            InitializeComponent();
        }

        /// <summary>
        /// create a new holistic file.
        /// </summary>
        private void miCreate_Click(object sender, EventArgs e)
        {
            CreateHolistic();
        }

        /// <summary>
        /// open holistic file
        /// </summary>
        private void miOpen_Click(object sender, EventArgs e)
        {
            OpenHolistic();
        }

        /// <summary>
        /// save holistic file.
        /// </summary>
        private void miSave_Click(object sender, EventArgs e)
        {
            if (_holisticFileInfo == null)
            {
                miSaveAs_Click(sender, e);
                return;
            }
            else
            {
                Save(_holisticFileInfo.DirectoryName);
            }
        }

        /// <summary>
        /// save holistic file as a new file.
        /// </summary>
        private void miSaveAs_Click(object sender, EventArgs e)
        {
            var result = folderBrowserDialog.ShowDialog(this);
            if (result != System.Windows.Forms.DialogResult.OK)
            {
                return;
            }
            var path = folderBrowserDialog.SelectedPath;
            Save(path);
        }

        private void miClose_Click(object sender, EventArgs e)
        {
            Clear();
        }

        /// <summary>
        /// Exist
        /// </summary>
        private void miExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        /// <summary>
        /// open editor
        /// </summary>
        private void treeHolistic_AfterSelect(object sender, TreeViewEventArgs e)
        {
            switch (e.Node.Level)
            {
                case 0:
                    OpenDatabaseSettingForm();
                    break;
                case 1:
                    OpenConfigurationSettingForm();
                    break;
                case 2:
                    OpenStatementSettingForm();
                    break;
            }
        }

        /// <summary>
        /// load setting form
        /// </summary>
        private void LoadSettingForm(Form form)
        {
            ClearSettingForm();
            form.TopLevel = false;
            form.Parent = this.panelEditorContainer;
            form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            form.Dock = DockStyle.Fill;
            form.Show();
        }

        /// <summary>
        /// clear setting form
        /// </summary>
        private void ClearSettingForm()
        {
            if (this.panelEditorContainer.HasChildren)
            {
                this.panelEditorContainer.Controls[0].Dispose();
                this.panelEditorContainer.Controls.Clear();
            }
        }

        /// <summary>
        /// open a existing holistic xml document.
        /// </summary>
        private void OpenHolistic()
        {
            var result = openFileDialog.ShowDialog(this);
            if (result != System.Windows.Forms.DialogResult.OK)
            {
                return;
            }

            Clear();

            var holisticDoc = new XmlDocument();
            holisticDoc.Load(openFileDialog.FileName);
            _holistic = new HolisticParser(holisticDoc).Holistic;

            // 解密连接字符串
            //foreach (var database in _holistic.Database)
            //{
            //    if (!string.IsNullOrEmpty(database.Protector))
            //    {
            //        IProtector protector = HolisticParser.CreateProtector(database.Protector);
            //        database.ConnectionString = protector.DecryptConnectionString(database.ConnectionString);
            //    }
            //}

            _holisticFileInfo = new FileInfo(openFileDialog.FileName);
            CacheTSQL();
            BuildHolisticTree();

            OpenProject(true);
        }

        /// <summary>
        /// create a new holistic xml document.
        /// </summary>
        private void CreateHolistic()
        {
            Clear();

            var holisticDoc = new XmlDocument();
            XmlElement rootNode = holisticDoc.CreateElement("Holistic", HOLISTIC_NAMESPACE);
            holisticDoc.AppendChild(rootNode);
            _holistic = new HolisticParser(holisticDoc).Holistic;
            BuildHolisticTree();

            OpenProject(true);
        }

        private void Clear()
        {
            treeHolistic.Nodes.Clear();
            panelEditorContainer.Controls.Clear();

            _holistic = null;
            _holisticFileInfo = null;
            _tsqlCache.Clear();
            OpenProject(false);
        }

        private void OpenProject(bool enabled)
        {
            this.miClose.Enabled = enabled;
            this.miSave.Enabled = enabled;
            this.miSaveAs.Enabled = enabled;
        }

        private void BuildHolisticTree()
        {
            treeHolistic.BeginUpdate();

            treeHolistic.Nodes.Clear();
            var rootNode = treeHolistic.Nodes.Add("Holistic", "Holistic");
            if (_holistic.Database != null)
            {
                foreach (var database in _holistic.Database)
                {
                    var databaseNode = rootNode.Nodes.Add(database.GetHashCode().ToString(), database.Name);
                    databaseNode.Tag = database;
                    databaseNode.ImageIndex = 1;
                    foreach (var config in database.Config)
                    {
                        var configNode = databaseNode.Nodes.Add(config.GetHashCode().ToString(), config.Name);
                        configNode.ImageIndex = 2;
                        configNode.Tag = config;
                    }
                }
            }
            rootNode.ExpandAll();
            treeHolistic.SelectedNode = rootNode;

            treeHolistic.EndUpdate();
            treeHolistic.Focus();
        }

        private void Save(string path)
        {
            XmlSerializerFactory factor = new XmlSerializerFactory();

            foreach (var database in _holistic.Database)
            {
                IProtector protector = null;
                if (!string.IsNullOrEmpty(database.Protector))
                {
                    protector = HolisticParser.CreateProtector(database.Protector);
                    database.ConnectionString = protector.EncryptConnectionString(database.ConnectionString);
                }

                foreach (var config in database.Config)
                {
                    var tsqlFileName = Path.Combine(path, config.FilePath);
                    var tsqlFileInfo = new FileInfo(tsqlFileName);
                    if (!Directory.Exists(tsqlFileInfo.DirectoryName))
                    {
                        Directory.CreateDirectory(tsqlFileInfo.DirectoryName);
                    }

                    using (XmlWriter writer = XmlWriter.Create(tsqlFileName))
                    {
                        factor.CreateSerializer(typeof(TSQL), TSQL_NAMESPACE).Serialize(writer, _tsqlCache[config.GetHashCode()]);
                    }

                    if (!string.IsNullOrEmpty(database.Protector))
                    {
                        protector.EncryptTSQLFile(tsqlFileName, tsqlFileName);
                    }
                }
            }

            var holisticFileName = Path.Combine(path, "Holistic.xml");
            using (XmlWriter writer = XmlWriter.Create(holisticFileName))
            {
                factor.CreateSerializer(typeof(Holistic), HOLISTIC_NAMESPACE).Serialize(writer, _holistic);
            }
        }

        private void miAbout_Click(object sender, EventArgs e)
        {
            FormAbout about = new FormAbout();
            about.ShowDialog(this);
        }
    }
}
